package study.alex.resumedb.gae;

import com.vaadin.addon.jpacontainer.EntityProvider;
import com.vaadin.addon.jpacontainer.JPAContainer;
import com.vaadin.addon.jpacontainer.JPAContainerFactory;
import com.vaadin.addon.jpacontainer.provider.CachingMutableLocalEntityProvider;
import com.vaadin.addon.jpacontainer.util.DefaultQueryModifierDelegate;
import study.alex.resumedb.gae.model.resumeTracker;

import javax.persistence.criteria.*;
import java.io.Serializable;
import java.util.List;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Created with IntelliJ IDEA.
 * User: alex
 * Date: 29.01.14
 * Time: 16:54
 * SVN $Id$
 */
public class JPAContainerForTracker extends JPAContainer<resumeTracker> implements Serializable {

    private void readObject(java.io.ObjectInputStream stream)
            throws java.io.IOException, ClassNotFoundException
    {
        stream.defaultReadObject();

        // assign reference manually.
        EntityProvider<resumeTracker> entityProvider =
                new CachingMutableLocalEntityProvider<resumeTracker>(resumeTracker.class, JPAContainerFactory.createEntityManagerForPersistenceUnit(EMF.PERSISTENCE_UNIT));
        setEntityProvider(entityProvider);

        getEntityProvider().setQueryModifierDelegate(
                new DefaultQueryModifierDelegate() {
                    @Override
                    public void queryHasBeenBuilt(CriteriaBuilder criteriaBuilder, CriteriaQuery<?> query) {
                        Logger.getLogger(JPAContainerForTracker.class.getName()).fine("Filter query: " + query);
                        super.queryHasBeenBuilt(criteriaBuilder, query);
                    }

                    @Override
                    public void filtersWillBeAdded(CriteriaBuilder criteriaBuilder, CriteriaQuery<?> query, List<Predicate> predicates) {
                        Root<?> fromTracker = query.getRoots().iterator().next();

                        Path<String> id = fromTracker.<String>get("id");
                        Logger.getLogger(JPAContainerForTracker.class.getName()).fine("Filter builder: path_id is " + id);
                        Logger.getLogger(JPAContainerForTracker.class.getName()).fine("Filter builder: query is " + query);
                        for (Predicate p : predicates) {
                            Logger.getLogger(JPAContainerForTracker.class.getName()).fine("Filter builder: predicate " + p);
                            List<Expression<Boolean>> expressions = p.getExpressions();
                            if (expressions != null && expressions.size() > 0) {
                                for (Expression<Boolean> e : expressions) {
                                    Logger.getLogger(JPAContainerForTracker.class.getName()).fine("Op: " + p.getOperator());
                                    Logger.getLogger(JPAContainerForTracker.class.getName()).fine("Expression: " + e);
                                }
                            } else
                                Logger.getLogger(JPAContainerForTracker.class.getName()).fine("Predicate Op: " + p.getOperator());

                            String escpId = id.toString().replace(".", "\\.");
                            StringBuilder regex = new StringBuilder();
                            regex.append("^\\(");
                            regex.append(escpId);
                            regex.append("\\s+=\\s+'(\\S+)'\\)\\s*$");

                            Pattern mask = Pattern.compile(regex.toString());
                            if (p.getOperator() == Predicate.BooleanOperator.AND) {
                                Matcher matcher = mask.matcher(p.toString());
                                if (matcher.matches()) {
                                    Logger.getLogger(JPAContainerForTracker.class.getName()).fine("Found target predicate: " + p);
                                    String targetId = matcher.group(1);
                                    Logger.getLogger(JPAContainerForTracker.class.getName()).fine("Target id is " + targetId);
                                    Predicate newPredicate = criteriaBuilder.equal(id, targetId);
                                    Logger.getLogger(JPAContainerForTracker.class.getName()).fine("New predicate: " + newPredicate);
                                    predicates.clear();
                                    predicates.add(p);
                                    break;
                                }
                            }

                        }
                        super.filtersWillBeAdded(criteriaBuilder, query, predicates);
                    }
                });

    }

    public JPAContainerForTracker() {
        super(resumeTracker.class);
    }
}